<template>
  <div class="lcd-db">
    <AForm layout="inline" class="lcd-db-form" :model="model" @finish="query">
        <AFormItem label="表名" name="name">
          <AInput v-model:value="model.name"/>
        </AFormItem>
      <AFormItem label="前缀" name="prefix">
        <AInput v-model:value="model.prefix"/>
      </AFormItem>
      <AButton type="primary" htmlType="submit">查询</AButton>
      <AButton style="margin-left: 8px" @click="genCode('java')">生成后端代码</AButton>
      <AButton style="margin-left: 8px" @click="genCode('vue')" :loading="javaModel.loading">下载前端代码</AButton>
    </AForm>
    <ATable size="small" :bordered="true" :columns="columns" :row-selection="rowSelection"
            :pagination="pagination" :data-source="ds" rowKey="name" class="lcd-db-table"
            :loading="javaModel.tableLoading">
      <template #action="{record}">
        <ATag class="lcd-ol-tag" color="#108ee9" @click="() => review(record)">源码预览</ATag>
      </template>
    </ATable>
    <AModal title="设置生成条件" v-model:visible="javaModel.visible" ref="javaRef">
      <AForm>
        <AFormItem label="是否覆盖" name="fileOverride">
          <ARadioGroup v-model:value="genModel.fileOverride">
            <ARadio :value="true">是</ARadio>
            <ARadio :value="false">否</ARadio>
          </ARadioGroup>
        </AFormItem>
        <AFormItem label="父菜单" name="menuId" extra="选择父菜单后会生成并导入对应的菜单">
          <ATreeSelect v-model:value="genModel.menuId" style="width: 100%"
              :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" :allowClear="true"
              :replaceFields="{key: 'id', title: 'name', value: 'id', children: 'children'}"
              :tree-data="menus" placeholder="请选择父菜单" tree-default-expand-all>
          </ATreeSelect>
        </AFormItem>
        <AFormItem label="输出到" name="writeTo">
          <ARadioGroup v-model:value="javaModel.writeTo" button-style="solid" @change="writeToChange">
            <ARadio :value="false">生成到指定目录</ARadio>
            <ARadio :value="true">直接生成到项目</ARadio>
          </ARadioGroup>
        </AFormItem>
        <AFormItem label="输出目录" name="outDir">
          <AInput v-model:value="genModel.outDir" readonly/>
        </AFormItem>
      </AForm>
      <template #footer>
        <div style="text-align: center">
          <AButton type="primary" @click="genSubmit" :loading="javaModel.loading">生成</AButton>
        </div>
      </template>
    </AModal>
    <ADrawer v-model:visible="drawerModel.visible" width="100%" :getContainer="false" :wrap-style="{ position: 'absolute' }">
      <template #title>
        <span>源码预览</span>
      </template>
      <a-tabs v-model:activeKey="drawerModel.activeKey" tab-position="right">
        <a-tab-pane key="vue" tab="vue"><pre>{{reviewModel.html}}</pre></a-tab-pane>
        <a-tab-pane key="entity" tab="entity"><pre>{{reviewModel.entity}}</pre></a-tab-pane>
        <a-tab-pane key="mapper" tab="mapper"><pre>{{reviewModel.mapper}}</pre></a-tab-pane>
        <a-tab-pane key="mapperXml" tab="mapperXml"><pre>{{reviewModel.mapperXml}}</pre></a-tab-pane>
        <a-tab-pane key="service" tab="service"><pre>{{reviewModel.service}}</pre></a-tab-pane>
        <a-tab-pane key="serviceImpl" tab="serviceImpl"><pre>{{reviewModel.serviceImpl}}</pre></a-tab-pane>
        <a-tab-pane key="controller" tab="controller"><pre>{{reviewModel.controller}}</pre></a-tab-pane>
      </a-tabs>
    </ADrawer>
  </div>
</template>

<script>
import {reactive, ref} from 'vue'
import {baseUrl} from "@/utils/http.utils";
import Utils from "@/utils/basic.utils";
export default {
  name: "index",
  setup() {
    let columns = ref([
      {dataIndex: 'name', title: '表名'},
      {dataIndex: 'entityName', title: '实体名'},
      {dataIndex: 'comment', title: '表注释'},
      {dataIndex: 'havePrimaryKey', title: '是否有主键'},
      {title: '操作', dataIndex: 'action', align: 'center', slots: {customRender: 'action'}},
    ])
    let menus = ref([]);
    let pagination = reactive({
      showSizeChanger: true,
      pageSizeOptions: ['10', '20', '30', '50', '100']
    })
    let genModel = reactive({
      outDir: null,
      tables: [],
      menuId: null,
      fileOverride: false
    });
    let javaModel = reactive({
      outDir: '',
      writeTo:false,
      visible: false,
      loading: false,
      tableLoading: false,
      fileOverride: false
    })
    let drawerModel = reactive({
      visible: false,
      activeKey: ''
    })
    let reviewModel = reactive({
      entity: '',
      html: '',
      mapper: '',
      mapperXml: '',
      service: '',
      serviceImpl: '',
      controller: ''
    })
    let rowSelection = reactive({
      onChange: (selectedRowKeys, selectedRows) => {
        genModel.tables = selectedRowKeys;
      }
    })
    let ds = ref([])
    let outDir = reactive({
      cusGenDir: '', // 自定义目录
      projectRoot: '', // 项目跟目录
    });
    let model = reactive({
      name: null,
      prefix: null
    })
    return {columns, pagination, ds, rowSelection, model, genModel, javaModel, outDir, menus, drawerModel, reviewModel};
  },
  mounted() {
    this.query(this.model);
    this.$http.get("/lcd/gen/getOutDir").then(({data, code}) => {
      if(code == 200) {
        this.outDir = data;
        this.genModel.outDir = this.outDir.cusGenDir;
      }
    }).catch(reason => console.error(reason))
    this.$http.get("/lcd/gen/parent").then(({data, code}) => {
      if(code == 200) {
        this.menus = data;
      }
    }).catch(reason => console.error(reason))
  },
  methods: {
    query(values) {
      this.javaModel.tableLoading = true;
      this.$http.get("/lcd/gen/list", {params: values})
          .then(({code, data, message}) => {
        if(code == 200) {
          this.ds = data;
        } else {
          this.$msg.errorMessage(message)
        }
      }).catch(reason => console.error(reason))
          .finally(() => this.javaModel.tableLoading = false)
    },
    genCode(type) {
        if(this.genModel.tables && this.genModel.tables.length > 0) {
          if(type == 'java') {
            this.javaModel.visible = true;
          } else {
            this.javaModel.loading = true;
            this.$http.post('/lcd/gen/vue', this.genModel).then(resp=> {
              let {code, message, data} = resp;
              if(code == 200) {
                let blob = Utils.base64toBlob(data, "application/zip")
                let downloadTag = document.createElement("a");
                downloadTag.href = window.URL.createObjectURL(blob);
                downloadTag.download = decodeURIComponent("ivzone.zip");
                // 兼容：某些浏览器不支持HTML5的download属性
                if (typeof downloadTag.download === 'undefined') {
                  downloadTag.setAttribute('target', '_blank')
                }
                document.body.appendChild(downloadTag);
                downloadTag.click();
                document.body.removeChild(downloadTag);
                window.URL.revokeObjectURL(downloadTag.href);
              } else {
                this.$msg.errorMessage(message);
              }
            }).finally(() => this.javaModel.loading = false)
          }
        } else {
          this.$msg.warningMessage("请选择要生成的表", 1)
        }
    },
    genSubmit() {
      this.javaModel.loading = true;
      this.$http.post('/lcd/gen/java', this.genModel).then(({data, code, message}) => {
        if(code == 200) {
          this.javaModel.visible = false;
          this.$msg.successMessage(`成功生成代码到[${this.genModel.outDir}]`)
        } else {
          this.$msg.errorMessage(message);
        }
      }).catch(reason => {console.error(reason)})
          .finally(() => this.javaModel.loading = false)
    },
    writeToChange(e) {
      let value = e.target.value;
      if(value) {  // 项目
        let projectRoot = this.outDir.projectRoot ? this.outDir.projectRoot : '';
        this.genModel.outDir = projectRoot + "\\src\\main\\java";
      } else {
        this.genModel.outDir = this.outDir.cusGenDir;
      }
    },
    review(table) {
      this.drawerModel.visible = true;
      this.$http.get('/lcd/gen/review', {params: {tableName: table.name}}).then(resp=>{
        if(resp['code'] == 200) {
          this.reviewModel = resp.data;
          this.drawerModel.activeKey='vue';
        } else {
          this.$msg.warningMessage(resp['message'])
        }
      }).catch(reason => this.$msg.errorMessage(reason))
    }
  }
}
</script>

<style scoped>
.lcd-db {
  padding: 10px 32px;
  position: relative;
}
.lcd-db-form {
  margin-bottom: 16px;
}
</style>